<template>
    <div class="uploadView"
         :style="'background:' + btn_style.background + ';color:' + btn_style.color
          + ';font-weight:' + btn_style.fontWeight + ';height:' + btn_style.height
           + ';width:' + btn_style.width + ';font-family:' + btn_style.fontFamily
            + ';border-radius:' + btn_style.borderRadius + ';font-size:' + btn_style.fontSize + ';border:' + btn_style.border">
        <lsj-upload
                ref="lsjUpload"
                :childId="Date.now() + ''"
                :width="width"
                :height="height"
                :option="{
                    url: upload_url,
                    name: upload_name,
                    header: {'token': this.$store.state.user.token},
                    formData: {
                        fileType,
                        profession
                    },
                }"
                :toBase="toBase"
                :size="size"
                :formats="formats"
                :debug="debug"
                :instantly="instantly"
                :distinct="distinct"
                @uploadEnd="onuploadEnd"
                @progress="onprogress"
                @change="onHandleChange">
            <view class="upload_view_btn">{{ btn_title }}</view>
        </lsj-upload>
        
        <!--    <view class="padding">
                <view>已选择文件列表：</view>
                <view v-for="(item,index) in files.values()" :key="index">
                    <image style="width: 100rpx;height: 100rpx;" :src="item.path" mode="widthFix"></image>
                    <text>blob：{{item.path}}</text>
                    <text>{{item.name}}</text>
                    <text style="margin-left: 10rpx;">大小：{{item.size}}</text>
                    <text style="margin-left: 10rpx;">状态：{{item.type}}</text>
                    <text style="margin-left: 10rpx;">进度：{{item.progress}}</text>
                    <text style="margin-left: 10rpx;" v-if="item.responseText">服务端返回演示：{{item.responseText}}</text>
                    <text @click="resetUpload(item.name)" v-if="item.type=='fail'" style="margin-left: 10rpx;padding: 0 10rpx;border: 1rpx solid #007AFF;">重新上传</text>
        &lt;!&ndash;            <text @click="clear(item.name)" style="margin-left: 10rpx;padding: 0 10rpx;border: 1rpx solid #007AFF;">删除</text>&ndash;&gt;
                    <text @click="clear(item, index)" style="margin-left: 10rpx;padding: 0 10rpx;border: 1rpx solid #007AFF;">删除</text>
                </view>
            </view>-->
    </div>
    </template>
    
    <script>
    
    import config from '@/config'
    
    const baseUrl = config.baseUrl
    export default {
        name: 'uploadView',
        data() {
            return {
                // 文件回显列表
                files: new Map(),
                // 微信小程序Map对象for循环不显示，所以转成普通数组，不要问为什么，我也不知道
                wxFiles: [],
                // 是否打印日志
                debug: true,
                
                // 必传宽高且宽高应与slot宽高保持一致
                width: '180rpx',
                height: '180rpx',
                // 演示用
                tabIndex: 0,
                list: [],
                filesValue: [],
                progressVisible: false,
            }
        },
        onReady() {
            /*setTimeout(()=>{
                console.log('----演示动态更新参数-----');
                this.$refs['lsjUpload'+this.tabIndex].setData('formData.orderId','动态设置的参数');
                
                console.log('以下注释内容为-动态更新参数更多演示，放开后可查看演示效果');
                // 修改option对象的name属性
                // this.$refs.lsjUpload.setData('name','myFile');
                
                // 修改option对象的formData内的属性
                // this.$refs.lsjUpload.setData('formData.appid','1111');
                
                // 替换option对象的formData
                // this.$refs.lsjUpload.setData('formData',{appid:'222'});
                
                // option对象的formData新增属性
                // this.$refs.lsjUpload.setData('formData.newkey','新插入到formData的属性');
                
                // ---------演示初始化值，用于已提交后再次编辑时需带入已上传文件-------
                // 方式1=传入数组
                // let files1 = [{name: '1.png'},{name: '2.png',}];
                
                // 方式2=传入Map对象
                // let files2 = new Map();
                // files2.set('1.png',{name: '1.png'})
                
                // 此处调用setFiles设置初始files
                // this.$refs.lsjUpload.setFiles(files1);
                
                // 初始化tab
                this.onTab(0);
            },2000)*/
        
        },
        props: {
            btn_style: {
                type: Object,
                default: function () {
                    return {
                        background: '#0084FF',
                        color: '#fff',
                        fontWeight: 600,
                        height: '100rpx',
                        width: '100%',
                        fontFamily: 'Poppins',
                        borderRadius: '16rpx',
                        fontSize: '32rpx',
                        border: 'none'
                    }
                }
            },
            btn_title: {
                type: String,
                default: '文件上传'
            },
            // 上传接口参数
        
            // 上传服务器地址，需要替换为你的接口地址
            upload_url: {
                type: String,
                default: ''
            },
            // 根据你接口需求自定义请求头,默认不要写content-type,让浏览器自适配
            /*upload_header: {
                type: String,
                default: ''
            },*/
            fileType: {
                type: Number,
                default: -1
            },
            profession: {
                type: Number,
                default: -1
            },
            // 上传附件的key
            upload_name: {
                type: String,
                default: ''
            },
            /**
             * 文件是否转为base64
             * false: file为文件流，app端跨浏览器不能将文件流返回到当前页面，但不影响上传file，app端如果是图片文件可通过绑定item.path到image标签src回显或者上传成功后服务端返回的服务器文件地址；
             * 【app和h5】true: file转base64，注意：转base64后若使用组件内置上传，file的值为base64串；
             * 【微信小程序】true: file转base64返回页面，内置上传用的临时路径item.path
             *
             * 提示：app端因为是跨浏览器的，所以不排除大文件转base64返回时url超长问题，目前只测了一般文件，若遇到那你只能自行改成sqlite或者localStroe
             * 温馨提示：：：：若无特殊需求不建议转base64，就不解释为什么了。
             * 温馨提示：：：：若无特殊需求不建议转base64，就不解释为什么了。
             * 温馨提示：：：：若无特殊需求不建议转base64，就不解释为什么了。
             */
            toBase: {
                type: Boolean,
                default: false
            },
            // 选择文件后是否立即自动上传，true=选择后立即上传
            instantly: {
                type: Boolean,
                default: true
            },
            // 选择文件是否去重
            distinct: {
                type: Boolean,
                default: false
            },
            // 限制允许上传的格式，空串=不限制，默认为空
            formats: {
                type: String,
                default: ''
            },
            // 文件上传大小限制
            size: {
                type: Number,
                default: 30
            },
            // 文件数量限制
            count: {
                type: Number,
                default: 1
            },
            // 是否多选
            multiple: {
                type: Boolean,
                default: true
            }
        },
        watch: {
            // 监听files变化，用于回显
            filesValue(newValue, oldValue) {
                console.log('filesValue changed:', newValue, oldValue);
                if (JSON.stringify(newValue) == JSON.stringify(oldValue)) {
                    this.$nextTick(() => {
                        console.log('filesValue changed:', false)
                        this.$emit('handleLoading', false)
                    })
                }
            }
        },
        methods: {
            // APP端 isPermissionInToast=false时，点击按钮检测到某项权限未授权时触发
            // 注意：不建议isPermissionInToast传false!!
            // 因为isPermissionInToast等于false时弹出的授权窗口用户点击同意后不会继续打开系统文件选择界面，需要用户再点一次选择文件按钮
            permissionBefore({permission, message}, childId) {
                console.log('permission', permission, message)
            },
            // APP端 用户有权限点击不同意时触发
            // 当isPermissionBuiltInHandle=false不使用组件内置弹框引导用户开启时，可在此函数内自定义弹框
            onpermissionFail({permission, message, result}, childId) {
                console.log('permission', permission, message, result);
            },
            // 某文件上传结束回调(成功失败都回调)
            onuploadEnd(item,childId) {
                console.log('666666', item)
                console.log(`${item.name}已上传结束，上传状态=${item.type}`)
                
                // 更新当前窗口状态变化的文件
                this.files.set(item.name, item)
                console.log('this.files', this.files)
                
                // ---可删除--演示上传完成后取服务端数据
                if (item['responseText']) {
                    this.$emit('getFiles', JSON.parse(item.responseText).data)
                    this.files.get(item.name).responseText = JSON.parse(item.responseText)
                }
                
                // 微信小程序Map对象for循环不显示，所以转成普通数组，
                // 如果你用不惯Map对象，也可以像这样转普通数组，组件使用Map主要是避免反复文件去重操作
                // #ifdef MP-WEIXIN
                this.wxFiles = [...this.files.values()];
                // #endif
                
                // 强制更新视图
                this.$forceUpdate();
                
                // ---可删除--演示判断是否所有文件均已上传成功
                let isAll = [...this.files.values()].find(item => item.type !== 'success')
                if (!isAll) {
                    console.log('已全部上传完毕')
                } else {
                    console.log(isAll.name + '待上传')
                }
                console.log('88最终文件列表', this.files.values())
                this.$emit('handleLoading', false)
            },
            // 上传进度回调，若md文档显示不出事件名称onprogress，如复制自行加上就行
            onprogress(item, childId) {
                this.$emit('progress', JSON.stringify(this.files.get(item.name)))
                console.log("🚀 ~ item:", item)
                // 更新当前状态变化的文件
                this.files.set(item.name, item)
                
                console.log('打印对象', JSON.stringify(this.files.get(item.name)))
                // 微信小程序Map对象for循环不显示，所以转成普通数组，不要问为什么，我也不知道
                // #ifdef MP-WEIXIN
                this.wxFiles = [...this.files.values()]
                // #endif
                
                // 强制更新视图
                this.$forceUpdate()
                
            },
    // 文件选择回调，若md文档显示不出事件名称onChange，如复制自行加上就行
            onHandleChange(files, childId) {
                this.$emit('handleLoading', true)
                console.log('当前选择的文件列表：', JSON.stringify([...files.values()]))
                // 更新选择的文件
                this.files = files
                this.filesValue = [...files.values()]
                // 强制更新视图
                this.$forceUpdate()
            
                // 微信小程序Map对象for循环不显示，所以转成普通数组，不要问为什么，我也不知道
                // #ifdef MP-WEIXIN
                this.wxFiles = [...files.values()]
                // #endif
        
        // ---可删除--演示重新定位覆盖层控件
        this.$nextTick(()=>{
            console.log('演示重新定位 (提示：像示例里文件列表在按钮上方时就需要插入文件后更新webview位置)');
            // 直接更新当前页面所有上传组件webview位置
            uni.$emit('$upload-show',{});
            
            // 也可以通过以下方式指定更新ref对应组件位置
            // this.$refs.lsjUpload0.show();
            // this.$refs.lsjUpload1.show();
            // this.$refs.lsjUpload2.show();
        });
        
    },
    // 手动上传
    upload() {
        // name=指定文件名，不指定则上传所有type等于waiting和fail的文件
        this.$refs['lsjUpload'+this.tabIndex].upload();
    },
    // 指定上传某个文件
    resetUpload(name) {
        this.$refs['lsjUpload'+this.tabIndex].upload(name);
    },
    // 移除某个文件
            clear(item, index) {
                // name=指定文件名，不传name默认移除所有文件
                // this.$refs['lsjUpload'+this.tabIndex].clear(name);
                this.files.values().forEach((temp, tIndex) => {
                    if (item.name === temp.name && index === tIndex) {
                        // 移除文件
                        this.files.delete(item.name)
                        // 更新视图
                        this.$forceUpdate()
                        // 移除文件后重新定位覆盖层位置
                        this.$nextTick(() => {
                        
                        })
                    }
                })
            },
    // ---可删除--演示在scroll中，scroll滚动后重新定位webview
    // 若md文档显示不出事件名称onscroll，如复制自行加上就行
            onscroll() {
                // #ifdef APP
                if (this.scrollTime) {
                    clearTimeout(this.scrollTime)
                }
                this.scrollTime = setTimeout(() => {
                    console.log('scroll结束调用show()')
                    this.$refs.lsjUpload1.show()
                }, 500)
                // #endif
            },
            /**
             * ---可删除--演示在组件上方添加新内容DOM变化
             */
            add() {
                this.list.push('DOM重排测试')
                // #ifdef APP
                this.$nextTick(() => {
                    // 更新当前页所有上传组件在页面中的位置
                    uni.$emit('$upload-show', {})
                })
        // #endif
    },
    /**
     * ---可删除--演示Tab切换时覆盖层是否能被点击
     * APP端因为是webview，层级比view高，此时若不希望点击触发选择文件，需要手动调用hide()
     * 手动调用hide后，需要调用show()才能恢复覆盖层的点击
     */
    onTab(tabIndex) {
        // 隐藏所有的控件（透明层）
        uni.$emit('$upload-hide', {})
        
        this.tabIndex = tabIndex
        // 显示允许点击的控件（透明层）
        this.$nextTick(() => {
            this.$refs['lsjUpload' + this.tabIndex].show()
        })
        
    }
        },
    }
    </script>
    
    <style scoped lang="scss">
    .uploadView {
        box-sizing: border-box;
        
        .upload_view_btn {
            width: 100%;
            height: 100%;
            display: flex;
            justify-content: center;
            align-items: center;
        }
    }
    
    ::v-deep {
        .lsj-file, .hFile {
            width: 100% !important;
            height: 100% !important;
        }
    }
    </style>